package com.lazyboyl.sharding.proxy.net.frontend;

import com.lazyboyl.sharding.proxy.net.proto.mysql.EOFPacket;
import com.lazyboyl.sharding.proxy.net.proto.mysql.FieldPacket;
import com.lazyboyl.sharding.proxy.net.proto.mysql.ResultSetHeaderPacket;
import com.lazyboyl.sharding.proxy.net.proto.mysql.RowDataPacket;
import com.lazyboyl.sharding.proxy.net.proto.parse.ServerParseShow;
import com.lazyboyl.sharding.proxy.net.proto.util.ByteUtil;
import com.lazyboyl.sharding.proxy.net.proto.util.Fields;
import com.lazyboyl.sharding.proxy.net.proto.util.PacketUtil;
import com.lazyboyl.sharding.proxy.net.proto.util.StringUtil;
import com.lazyboyl.sharding.proxy.net.response.ShowColumns;
import com.lazyboyl.sharding.proxy.net.response.ShowDatabases;
import com.lazyboyl.sharding.proxy.net.response.ShowTables;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * ShowHandler
 *
 * @Author lizhuyang
 */
public final class ShowHandler {

    public static void handle(String stmt, FrontendConnection connection, int offset) {
        int type = ServerParseShow.parse(stmt, offset);
        switch (type) {
            // 展示数据库
            case ServerParseShow.DATABASES:
                ShowDatabases.response(connection);
                break;
            // 展示某张表的column字段信息
            case ServerParseShow.TABLE_COLUMNS:
                ShowColumns.response(connection);
                break;
            default:
                Map<String, Object> queryResult = new HashMap<>();
                queryResult.put("net_buffer_length", 16384);
                queryResult.put("interactive_timeout", 28800);
                queryResult.put("query_cache_size", 1048576);
                queryResult.put("character_set_connection", "utf8");
                queryResult.put("max_allowed_packet", 4194304);
                queryResult.put("net_write_timeout", 60);
                queryResult.put("lower_case_table_names", 1);
                queryResult.put("system_time_zone", "");
                queryResult.put("tx_isolation", "REPEATABLE-READ");
                queryResult.put("wait_timeout", 28800);
                queryResult.put("time_zone", "SYSTEM");
                queryResult.put("character_set_server", "utf8");
                queryResult.put("character_set_client", "utf8");
                queryResult.put("sql_mode", "IGNORE_SPACE,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION");
                queryResult.put("character_set_results", "utf8");
                queryResult.put("transaction_isolation", "REPEATABLE-READ");
                queryResult.put("query_cache_type", "OFF");
                queryResult.put("init_connect", "");
                int FIELD_COUNT = 18;
                ResultSetHeaderPacket header = PacketUtil.getHeader(FIELD_COUNT);
                FieldPacket[] fields = new FieldPacket[FIELD_COUNT];
                EOFPacket eof = new EOFPacket();
                byte packetId = 0;
                int i = 0;
                header.packetId = ++packetId;
                for (Map.Entry<String, Object> entry : queryResult.entrySet()) {
                    fields[i] = PacketUtil.getField(entry.getKey(), Fields.FIELD_TYPE_VAR_STRING);
                    fields[i++].packetId = ++packetId;
                }
                eof.packetId = ++packetId;

                ChannelHandlerContext ctx = connection.getCtx();
                ByteBuf buffer = ctx.alloc().buffer();
                buffer = header.writeBuf(buffer, ctx);
                for (FieldPacket field : fields) {
                    buffer = field.writeBuf(buffer, ctx);
                }
                buffer = eof.writeBuf(buffer, ctx);

                byte packetIdNew = eof.packetId;
                RowDataPacket row = new RowDataPacket(FIELD_COUNT);
                for (Map.Entry<String, Object> entry : queryResult.entrySet()) {
                    Object obj = queryResult.get(entry.getKey());
                    if (obj instanceof String) {
                        row.add(StringUtil.encode((String) obj, "gbk"));
                    } else if (obj instanceof LocalDateTime) {
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                        String localTime = df.format((LocalDateTime) obj);
                        row.add(StringUtil.encode(localTime, "gbk"));
                    } else if (obj instanceof Date) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        String localTime = sdf.format((Date) obj);
                        row.add(StringUtil.encode(localTime, "gbk"));
                    } else if (obj instanceof Long) {
                        Long l = (Long) obj;
                        row.add(StringUtil.encode(Long.toString(l), "gbk"));
                    } else if (obj instanceof Integer) {
                        Integer integer = (Integer) obj;
                        row.add(StringUtil.encode(Integer.toString(integer), "gbk"));
                    } else {
                        row.add(ByteUtil.getBytes(obj));
                    }
                }
                row.packetId = ++packetIdNew;
                buffer = row.writeBuf(buffer, ctx);
                EOFPacket lastEof = new EOFPacket();
                lastEof.packetId = ++packetIdNew;
                buffer = lastEof.writeBuf(buffer, ctx);
                ctx.writeAndFlush(buffer);
                break;
//            // 展示某个数据库的表的集合
//            default:
//                ShowTables.response(connection);
//                break;
        }

    }
}